package com.lh.utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class SignatureGenerator {

    /**
     * 生成签名
     * @param params 待签名的参数集合
     * @param key BJCA颁发的密钥
     * @param algorithm 签名算法，如"HmacSHA256"
     * @return 生成的签名
     * @throws Exception 可能的加密异常
     */
    public static String generateSignature(Map<String, String> params, String key, String algorithm) throws Exception {
        // 第一步：处理参数并排序
        String stringA = buildStringA(params);

        // 第二步：HMAC运算并Base64编码
        return hmacAndBase64(stringA, key, algorithm);
    }

    /**
     * 构建字符串stringA
     * 规则：非空参数按参数名ASCII码从小到大排序，用key=value&拼接
     */
    private static String buildStringA(Map<String, String> params) {
        // 使用TreeMap自动按key的ASCII码排序
        TreeMap<String, String> sortedParams = new TreeMap<>(params);

        StringBuilder stringA = new StringBuilder();

        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();

            // 跳过空值参数
            if (value == null || value.trim().isEmpty()) {
                continue;
            }

            // 拼接key=value
            if (stringA.length() > 0) {
                stringA.append("&");
            }
            stringA.append(key).append("=").append(value);
        }

        return stringA.toString();
    }

    /**
     * 进行HMAC运算并对结果进行Base64编码
     */
    private static String hmacAndBase64(String data, String key, String algorithm) throws Exception {
        // 创建HMAC实例
        Mac mac = Mac.getInstance(algorithm);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
        mac.init(secretKeySpec);

        // 计算HMAC
        byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));

        // Base64编码
        return Base64.getEncoder().encodeToString(hmacBytes);
    }

    // 测试方法
    public static void main(String[] args) {
        try {
            // 示例参数
            Map<String, String> params = new HashMap<>();
            params.put("appId", "10002");
            params.put("deviceId", "1000");
            params.put("mobile", "18611525990");
            params.put("signAlgo", "HmacSHA256");

            // 假设这是BJCA颁发的密钥
            String key = "your_secret_key_from_bjca";

            // 生成签名
            String signature = generateSignature(params, key, "HmacSHA256");

            System.out.println("stringA: " + buildStringA(params));
            System.out.println("signature: " + signature);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}